package com.xbongbong.saas.help;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.MultiUnitItemPoJo;
import com.xbongbong.paas.field.UnitItemPoJo;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.pojo.MultiFieldPricePojo;
import com.xbongbong.paas.pojo.MultiUnitPricePoJo;
import com.xbongbong.paas.pojo.ProductFieldPojo;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.CalendarUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.form.pojo.dto.ChildProductDTO;
import com.xbongbong.pro.formdata.pojo.dto.SaasAnalysisDataDTO;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainDTO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ProductConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.BusinessUnitProductEntity;
import com.xbongbong.saas.domain.entity.PayBalanceEntity;
import com.xbongbong.saas.domain.entity.PaymentBalanceEntity;
import com.xbongbong.saas.domain.entity.ProductUnitPriceEntity;
import com.xbongbong.saas.domain.entity.ProductUnitRateEntity;
import com.xbongbong.saas.domain.entity.ProductWarehouseEntity;
import com.xbongbong.saas.domain.entity.SpecificationEntity;
import com.xbongbong.saas.domain.entity.SupplierProductEntity;
import com.xbongbong.saas.domain.entity.ext.ContactEntityExt;
import com.xbongbong.saas.enums.BirthdayTypeEnum;
import com.xbongbong.saas.enums.ProductNotifyEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContactEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.subform.ProductWarehouseSubFormEnum;
import com.xbongbong.saas.model.ContactModel;
import com.xbongbong.saas.model.PayBalanceModel;
import com.xbongbong.saas.model.PaymentBalanceModel;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.saas.model.ProductUnitPriceModel;
import com.xbongbong.saas.model.ProductUnitRateModel;
import com.xbongbong.saas.model.ProductWarehouseModel;
import com.xbongbong.saas.model.SpecificationModel;
import com.xbongbong.saas.model.SupplierProductModel;
import com.xbongbong.saas.model.WarehouseModel;
import com.xbongbong.saas.service.toolbox.help.AttrDecimalPrecisionHelper;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getLongOrDefaultFromFormData;
import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getStringOrDefaultFromFormData;

@Component
public class ShowFormatHelp {

    @Resource
    private PaymentBalanceModel paymentBalanceModel;
    @Resource
    private PayBalanceModel payBalanceModel;
    @Resource
    private ContactModel contactModel;

    @Resource
    private SaasFormHelp saasFormHelp;
    @Resource
    private SpecificationModel specificationModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private ProductUnitPriceModel productUnitPriceModel;
    @Resource
    private ProductUnitRateModel productUnitRateModel;
    @Resource
    private AttrDecimalPrecisionHelper attrDecimalPrecisionHelper;
    @Resource
    private SupplierProductModel supplierProductModel;
    @Resource
    private WarehouseModel warehouseModel;
    @Resource
    private ProductWarehouseModel productWarehouseModel;
    @Resource
    private ProductModel productModel;


    /**
     * 将数据库中的生日三个字段转换成json对象格式给前端显示
     *
     * @param result     前端传回的data数据
     * @param attr       要格式化的字段attr
     * @author chaoxiong.lei
     * @date 15:38 2019/1/21
     * @since v1.0
     **/
    public void formatBirthday4Show(JSONObject result, String attr, String birthdayFlag) throws XbbException {
        if (result == null || attr == null || birthdayFlag == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
        }
        try {
            // 获取生日是公历还是阴历
            Integer flag = result.getInteger(birthdayFlag);
            String birthday = result.getString(attr);
            if (!DateTimeUtil.isSDFDate(birthday)) {
                return;
            }
            JSONObject jsonObject = new JSONObject();
            if (Objects.equals(flag, BirthdayTypeEnum.LUNAR_BIRTHDAY.getValue())) {
                // 阴历生日
                jsonObject.put(StringConstant.BIRTHDAY_FLAG, flag);
                jsonObject.put(StringConstant.BIRTHDAY, birthday);
                jsonObject.put(StringConstant.VALUE, CalendarUtil.lunar2Str(birthday));
                result.put(attr, jsonObject);
            } else if (Objects.equals(flag, BirthdayTypeEnum.BIRTHDAY.getValue())) {
                // 公历生日
                jsonObject.put(StringConstant.BIRTHDAY_FLAG, flag);
                jsonObject.put(StringConstant.BIRTHDAY, birthday);
                jsonObject.put(StringConstant.VALUE, birthday);
                result.put(attr, jsonObject);
            }
            result.put(birthdayFlag, null);
        } catch (Exception e) {
            // 类型转换异常
//            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100015);
        }
    }

    /**
     * 将数据库中的两个字段转换成json对象格式给前端显示
     *
     * @param result     前端传回的data数据
     * @param attr       要格式化的字段attr
     * @param linkedAttr 格式化字段对应的隐藏字段
     * @author chaoxiong.lei
     * @date 15:38 2019/1/21
     * @since v1.0
     **/
    public void formatLinkBusiness4Show(JSONObject result, String attr, String linkedAttr, Integer fieldType) throws XbbException {
        if (result == null || attr == null || linkedAttr == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
        }
        formatListBusiness4ShowBase(result,attr,linkedAttr,fieldType,null, null,null);
    }

    public void formatLinkBusiness4Show4List(JSONObject result, String attr, String linkedAttr, Integer fieldType,Integer linkBusinessType) throws XbbException {
        formatListBusiness4ShowBase(result,attr,linkedAttr,fieldType,linkBusinessType, null,null);
    }

    public void formatListBusiness4ShowBase(JSONObject result, String attr, String linkedAttr, Integer fieldType,Integer linkBusinessType, Integer sourceBusinessType, String corpid) throws XbbException {
        JSONArray jsonArray = new JSONArray();
        try {
            // 获取关联业务的id
            String businessIdStr = result.getString(attr);
            // 获取关联业务的名称
            String businessNameStr = result.getString(linkedAttr);
            Double advancePaymentBalance = null;
            if (Objects.equals(linkBusinessType, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())
                    && (Objects.equals(sourceBusinessType, XbbRefTypeEnum.CONTRACT.getCode())
                    || Objects.equals(sourceBusinessType, XbbRefTypeEnum.SALES_OPPORTUNITY.getCode())
                    || Objects.equals(sourceBusinessType, XbbRefTypeEnum.QUOTATION.getCode()))) {
                PaymentBalanceEntity paymentBalanceEntity = paymentBalanceModel.getByCustomerId(getLongOrDefaultFromFormData(result, attr, 0L), corpid);
                if (paymentBalanceEntity == null) {
                    advancePaymentBalance = 0D;
                } else {
                    advancePaymentBalance = paymentBalanceEntity.getAdvancePaymentBalance();
                }
            }
            //进销存付款单处理
            boolean jxcPaySheetLinkFlag = Objects.equals(linkBusinessType, XbbRefTypeEnum.SUPPLIER.getCode()) && Objects.equals(sourceBusinessType, XbbRefTypeEnum.PURCHASE.getCode());
            if (jxcPaySheetLinkFlag) {
                PayBalanceEntity payBalanceEntity = payBalanceModel.getBySupplierId(getLongOrDefaultFromFormData(result, attr, 0L), corpid);
                if (payBalanceEntity == null) {
                    advancePaymentBalance = 0D;
                } else {
                    advancePaymentBalance = payBalanceEntity.getAdvancePayBalance();
                }
            }
            if (StringUtil.isNotEmpty(businessIdStr)) {
                // 关联业务不是必填，所以可能没有值
                List<String> businessIdList;
                List<String> businessNameList = new ArrayList<>();
                if (Objects.equals(FieldTypeEnum.LINK_BUSINESS_MULTI.getType(), fieldType)) {
                    // 鲁江：下拉多选不要用逗号或者竖线分割，存成array
                    businessIdStr = JSONObject.toJSONString(result.get(attr));
                    businessIdList = JSON.parseArray(businessIdStr, String.class);
                    if ( StringUtil.isNotEmpty(businessNameStr)) {
                        businessNameStr = JSONObject.toJSONString(result.get(linkedAttr));
                        businessNameList = JSON.parseArray(businessNameStr, String.class);
                    }
                } else {
                    businessIdList = Collections.singletonList(businessIdStr);
                    if ( StringUtil.isNotEmpty(businessNameStr)) {
                        businessNameList = Collections.singletonList(businessNameStr);
                    }
                }

                for (int i = 0; i < businessIdList.size(); i++) {
                    Long businessId = Long.valueOf(businessIdList.get(i));
                    String businessName;
                    if (CollectionsUtil.isNotEmpty(businessNameList) && i < businessNameList.size()) {
                        businessName = businessNameList.get(i);
                    } else {
                        businessName = "";
                    }
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_ID, businessId);
                    jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_NAME, businessName);
                    jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_LINK_TYPE, linkBusinessType);
                    jsonObject.put(StringConstant.SAAS_LINK_ADVANCE_PAYMENT_BALANCE, advancePaymentBalance);
                    jsonArray.add(jsonObject);
                }
                result.put(attr, jsonArray);
                result.put(linkedAttr, null);
            }
        } catch (Exception e) {
            // 类型转换异常或数组下标越界
//            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100015);
        }
    }

    /**
     * 目前这个方法主要是为了获取合同重的客户的可核销预收款金额，其他暂时切勿调用
     * @param result
     * @param attr
     * @param linkedAttr
     * @param fieldType
     * @param linkBusinessType
     * @param sourceBusinessType
     * @param corpid
     * @throws XbbException
     * @author chenshan
     * @date 2019-12-01 12:27
     */
    public void formatLinkBusiness4ShowBySource(JSONObject result, String attr, String linkedAttr, Integer fieldType,Integer linkBusinessType, Integer sourceBusinessType, String corpid) throws XbbException {
        if (result == null || attr == null || linkedAttr == null || linkBusinessType == null || sourceBusinessType == null || corpid == null ) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
        }
        formatListBusiness4ShowBase(result,attr,linkedAttr,fieldType,linkBusinessType, sourceBusinessType, corpid);
    }

    /**
     * 将数据库中文本加勾选两个值转换成json对象格式给前端显示（如bom版本）
     *
     * @param result     前端传回的data数据
     * @param attr       要格式化的字段attr
     * @param linkedAttr 字段隐藏
     * @author feng.zheng
     * @date 19:18 2019/1/31
     * @since v1.0
     **/
    public void formatTextCheck4Show(JSONObject result, String attr, String linkedAttr) throws XbbException {
        if (result == null || attr == null || linkedAttr == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
        }
        try {
            String value = result.getString(attr);
            Integer checked = result.getInteger(linkedAttr);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put(StringConstant.VALUE, value);
            jsonObject.put(StringConstant.CHECKED, checked);
            result.put(linkedAttr,null);
            result.put(attr, jsonObject);
        } catch (Exception e) {
            // 类型转换异常
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100015);
        }
    }

    /**
     * 将数据库中文本加勾选两个值转换成json对象格式给前端显示（如bom版本）
     *
     * @param result     前端传回的data数据
     * @param attr       要格式化的字段attr
     * @param communicateBusinessType 字段隐藏
     * @param communicateBusinessLinkText 字段隐藏
     * @author feng.zheng
     * @date 19:18 2019/1/31
     * @since v1.0
     **/
    public void formatCommunicateBusiness4Show(JSONObject result, String attr, String communicateBusinessType, String communicateBusinessLinkText) throws XbbException {
        if (result == null || attr == null || communicateBusinessType == null || communicateBusinessLinkText == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
        }
        try {
            String id = result.getString(attr);
            if (Objects.isNull(id) || Objects.equals("0", id)) {
                return;
            }
            Integer businessType = result.getInteger(communicateBusinessType);
            String name = result.getString(communicateBusinessLinkText);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put(StringConstant.BUSINESS_TYPE, businessType);
            jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_ID, id);
            jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_NAME, name);
            result.put(communicateBusinessType, null);
            result.put(communicateBusinessLinkText, null);
            result.put(attr, jsonObject);

        } catch (Exception e) {
            // 类型转换异常
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100015);
        }

    }

    /**
     * youli.chen
     * 实时获取跟进记录联系人
     * @param result
     * @param attr
     * @param linkedAttr
     * @param fieldType
     * @param corpid
     * @throws XbbException
     */
    public void realTime4CommunicateContact(JSONObject result, String attr, String linkedAttr, Integer fieldType, String corpid) throws XbbException {
        JSONArray jsonArray = new JSONArray();
        try {
            // 获取关联业务的id
            String businessIdStr = result.getString(attr);

            if (StringUtil.isNotEmpty(businessIdStr)) {
                List<ContactEntityExt> contactEntityExts = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                // 关联业务不是必填，所以可能没有值
                List<Long> businessIdList;
                if (Objects.equals(FieldTypeEnum.LINK_BUSINESS_MULTI.getType(), fieldType)) {
                    // 鲁江：下拉多选不要用逗号或者竖线分割，存成array
                    businessIdStr = JSONObject.toJSONString(result.get(attr));
                    businessIdList = JSON.parseArray(businessIdStr, Long.class);
                    if (CollectionUtils.isNotEmpty(businessIdList)) {
                        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        params.put("corpid", corpid);
                        params.put("idIn", businessIdList);
                        params.put("del", DelEnum.NORMAL.getDel());
                        contactEntityExts = contactModel.findEntitys(params);
                    }
                }
                if(CollectionUtils.isNotEmpty(contactEntityExts)){
                    for(ContactEntityExt contactEntityExt : contactEntityExts){
                        Long businessId = contactEntityExt.getId();
                        String businessName = getStringOrDefaultFromFormData(contactEntityExt.getData(), ContactEnum.NAME.getAttr(), "");
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_ID, businessId);
                        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_NAME, businessName);
                        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_LINK_TYPE, null);
                        jsonObject.put(StringConstant.SAAS_LINK_ADVANCE_PAYMENT_BALANCE, null);
                        jsonArray.add(jsonObject);
                    }
                }
                result.put(attr, jsonArray);
                result.put(linkedAttr, null);
            }
        } catch (Exception e) {
            // 类型转换异常或数组下标越界
//            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100015);
        }
    }


    /**
     * 字段格式转换，展示给前端
     * 该字段比较特殊，就不写公共方法
     *
     * @param data 前端传回的data数据
     * @throws XbbException 参数格式错误异常
     * @author chaoxiong.lei
     * @date 15:38 2019/1/21
     * @since v1.0
     **/
    public void format4Show(SaasAnalysisDataDTO saasAnalysisDataDTO, JSONObject data) throws XbbException {
        String corpid = saasAnalysisDataDTO.getCorpid();
        // 产品编辑，编辑的是父产品
        Long parentProductId = saasAnalysisDataDTO.getDataId();
        ChildProductDTO childProductDTO = new ChildProductDTO();
        childProductDTO.setCorpid(corpid);
        childProductDTO.setParentProductId(Arrays.asList(parentProductId));
        List<PaasFormDataEntityExt> originProductList = productModel.getChildProductList(childProductDTO);

        // 是否是多单位
        boolean enableMultiUnit = Objects.equals(data.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE);
        Map<Long, List<UnitItemPoJo>> groupMap = new HashMap<>();
        if (enableMultiUnit) {
            ProductFieldPojo productFieldPojo = saasFormHelp.getProductFieldPojo(RedisPrefixConstant.PRODUCT_UNIT, ProductEnum.UNIT.getAttr(), corpid);
            groupMap = productFieldPojo.getMultiItems().stream().collect(Collectors.toMap(MultiUnitItemPoJo::getValue, MultiUnitItemPoJo::getItemDataPoJoList));
        }
        PaasFormExplainEntity formExplainEntity = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.PRODUCT.getCode(),corpid);
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(formExplainEntity.getExplains());
        //产品成本可见权限
        boolean costVisible=true;
        if (Objects.nonNull(saasAnalysisDataDTO.getLoginUser())){
            HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
            handlerExplainDTO.setLoginUser(saasAnalysisDataDTO.getLoginUser());
            handlerExplainDTO.setUserId(saasAnalysisDataDTO.getLoginUser().getUserId());
            //产品成本权限
            FieldAttrEntity costFieldPojo = explainMap.get(ProductEnum.COST.getAttr());
            costVisible = Objects.equals(costFieldPojo.getVisible(), 1) && !ExplainUtil.invisibleOfScope(costFieldPojo, handlerExplainDTO);
        }
        // 从解释中获取成本和单价的精度设置
        Integer priceAccuracy = explainMap.get(ProductEnum.PRICE.getAttr()).getAccuracy();
        JSONObject specificationObj = new JSONObject();
        // 高级模式
        Integer advancedMode = data.getInteger(ProductEnum.SPECIFICATION.getAttr());
        advancedMode = advancedMode == null ? 0 : advancedMode;
        // 父产品下的子产品
        if (originProductList == null) {
            originProductList = new ArrayList<>();
        }
        Map<Long, PaasFormDataEntityExt> childMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasFormDataEntityExt paasFormDataEntityExt : originProductList) {
            //处理成本是否可见
            if (!costVisible && Objects.equals(saasAnalysisDataDTO.getPlatform(), PlatFormEnum.DINGTALK.getValue())){
                paasFormDataEntityExt.getData().put(ProductEnum.COST.getAttr(),BasicConstant.ZERO_DOUBLE);
            }
            childMap.put(paasFormDataEntityExt.getId(), paasFormDataEntityExt);
        }
        specificationObj.put(ProductConstant.ADVANCED_MODE, advancedMode);
        Double totalStock = 0D;
        if (Objects.equals(advancedMode, 0)) {
            if (!originProductList.isEmpty()) {
                PaasFormDataEntityExt entity = originProductList.get(0);
                JSONObject dataList = entity.getData();
                // 规格
                String specification = dataList.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr());
                specificationObj.put(ProductConstant.SINGLE_SPEC, specification);
                // 条码
                String barcode = dataList.getString(ProductEnum.BARCODE.getAttr());
                // 单规格获取唯一子产品的条码 多规格的条码在SPECIFICATION字段处处理
                data.put(ProductEnum.BARCODE.getAttr(), barcode);
                //单规格成本，兼容迁移数据
                data.put(ProductEnum.COST.getAttr(),dataList.getDouble(ProductEnum.COST.getAttr()));
                data.put(ProductEnum.STOCK.getAttr(),dataList.getDouble(ProductEnum.STOCK.getAttr()));
            }
            if (enableMultiUnit) {
                List<ProductUnitPriceEntity> entitys = productUnitPriceModel.getPriceEntitysByParentId(corpid, parentProductId);
                if (!entitys.isEmpty()) {
                    ProductUnitPriceEntity entity = entitys.get(0);
                    JSONArray price = entity.getPrice();
                    List<UnitItemPoJo> unitItemPoJos = groupMap.get(entity.getUnitGroupId());
                    List<MultiUnitPricePoJo> multiUnitPricePoJos = price.toJavaList(MultiUnitPricePoJo.class);
                    Map<Long, String> multiUnitNameMap = new HashMap<>();
                    unitItemPoJos.forEach(item->multiUnitNameMap.put(item.getValue(), item.getText()));
                    for (MultiUnitPricePoJo itemPoJo : multiUnitPricePoJos) {
                        String name = multiUnitNameMap.get(itemPoJo.getValue());
                        if (Objects.nonNull(name)) {
                            itemPoJo.setText(name);
                        }
                    }
                    price = JSONArray.parseArray(JSON.toJSONString(multiUnitPricePoJos));
                    if (unitItemPoJos.size() != price.size()){
                        price = productModel.formatMultiPrice(unitItemPoJos, price);
                    }
                    data.put(ProductEnum.PRICE.getAttr(), price);
                    if (Objects.equals(saasAnalysisDataDTO.getPlatform(), StringConstant.PLATFORM_DINGTALK)){
                        //移动端格式不一样
                        List<PaasFormDataEntityExt> multiProductList = new ArrayList<>();
                        for (int i = 0; i < price.size(); i++) {
                            JSONObject child = (JSONObject) price.get(i);
                            child.put(BasicConstant.RATE, new BigDecimal(child.getDoubleValue(BasicConstant.RATE)).setScale(priceAccuracy, BigDecimal.ROUND_HALF_UP).toPlainString());
                            child.put(ProductEnum.PRICE.getAttr(), child.getDoubleValue(BasicConstant.RATE));
                            PaasFormDataEntityExt entityExt = new PaasFormDataEntityExt();
                            entityExt.setData(child);
                            multiProductList.add(entityExt);
                        }
                        //多单位产品都需要做价格排序
                        String priceStr = productModel.getPriceOrCostRegion(multiProductList, ProductEnum.PRICE.getAttr(), priceAccuracy);
                        data.put(ProductEnum.PRICE.getAttr(), priceStr);
                    }
                }
            }
        } else if (Objects.equals(advancedMode, 1)) {
            Map<Long, Object> multiUnitPriceMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            //移动端格式不一样
            List<PaasFormDataEntityExt> multiProductList = new ArrayList<>();
            if (enableMultiUnit) {
                List<ProductUnitPriceEntity> entitys = productUnitPriceModel.getPriceEntitysByParentId(corpid, parentProductId);
                for (ProductUnitPriceEntity entity : entitys) {
                    JSONArray price = entity.getPrice();
                    List<UnitItemPoJo> unitItemPoJos = groupMap.get(entity.getUnitGroupId());
                    if (unitItemPoJos.size() != price.size()){
                        price = productModel.formatMultiPrice(unitItemPoJos, price);
                    }
                    multiUnitPriceMap.put(entity.getProductId(), price);
                    if (Objects.equals(saasAnalysisDataDTO.getPlatform(), StringConstant.PLATFORM_DINGTALK)){
                        for (int i = 0; i < price.size(); i++) {
                            JSONObject child = (JSONObject) price.get(i);
                            child.put(BasicConstant.RATE, new BigDecimal(child.getDoubleValue(BasicConstant.RATE)).setScale(priceAccuracy, BigDecimal.ROUND_HALF_UP).toPlainString());
                            child.put(ProductEnum.PRICE.getAttr(), child.getDoubleValue(BasicConstant.RATE));
                            PaasFormDataEntityExt entityExt = new PaasFormDataEntityExt();
                            entityExt.setData(child);
                            multiProductList.add(entityExt);
                        }
                    }
                }

                long unitGroupId = data.getLongValue(ProductEnum.UNIT.getAttr());
                Map<String, Object> param = new HashMap<>();
                param.put("corpid", corpid);
                param.put("del", 0);
                param.put("groupId", unitGroupId);
                List<ProductUnitRateEntity> unitRateEntitys = productUnitRateModel.findEntitys(param);
                List<MultiFieldPricePojo> unitItemPoJos = new ArrayList<>();
                for (int i = 0; i < unitRateEntitys.size(); i++) {
                    ProductUnitRateEntity productUnitRateEntity = unitRateEntitys.get(i);
                    MultiFieldPricePojo poJo = new MultiFieldPricePojo();
                    poJo.setAttr(SelectProductEnum.PRICE.getSaasAttr() + "_"  + i);
                    poJo.setAttrName(ProductEnum.PRICE.getAttrName() + "(" + productUnitRateEntity.getName() + ")");
                    poJo.setSaasAttr(SelectProductEnum.PRICE.getSaasAttr() + i);
                    poJo.setValue(productUnitRateEntity.getId());
                    unitItemPoJos.add(poJo);
                }
                specificationObj.put(ProductConstant.PRICE_EXPLAINS, unitItemPoJos);
            }
            JSONArray specificationArray = specificationModel.getSpecificationArray(corpid, parentProductId);
            specificationObj.put(ProductConstant.SPEC_VALUE, specificationArray);
            // specKey配合前端性能优化
            Map<Integer,List> map = new HashMap(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<String> nameList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (Integer i = 0;i < specificationArray.size();i++){
                JSONObject nameValue = specificationArray.getJSONObject(i);
                String name = nameValue.getString("name");
                JSONArray value = nameValue.getJSONArray("value");
                List<String> list = new ArrayList<>();
                for (int j = 0;j<value.size();j++){
                    String valueStr = value.getString(j);
                    list.add(valueStr);
                }
                map.put(i,list);
                nameList.add(name);
            }
            JSONArray specDetails = new JSONArray();
            StringBuilder s1 = new StringBuilder();
            StringBuilder s2 = new StringBuilder();
            StringBuilder s3 = new StringBuilder();
            List<String> c1 = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<String> c2 = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<String> c3 = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (Objects.nonNull(map.get(0))){
                c1 = map.get(0);
                s1.append(nameList.get(0));
            }
            if (Objects.nonNull(map.get(1))){
                c2 = map.get(1);
                s2.append(nameList.get(1));
            }
            if (Objects.nonNull(map.get(2)) ){
                c3 = map.get(2);
                s3.append(nameList.get(2));
            }
            Collections.sort(originProductList , Comparator.comparing(a -> a.getData().getLong(ProductEnum.TEMP_STOCK.getAttr())));
            Map dataMap = makeDataMap(originProductList,s1,c1,s2,c2,s3,c3);
            int len1 = c1.size();
            int len2 = c2.size();
            int len3 = c3.size();
            List<String> specKeyList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (int i = 0; i < len1; i++) {
                String one = c1.get(i);
                if (len2 > 0) {
                    for (int j = 0; j < len2; j++) {
                        String two = c2.get(j);
                        if (len3 > 0) {
                            for (int q = 0; q < len3; q++) {
                                String three = c3.get(q);
                                String specKey = s1.toString() + ":" + one + "," + s2.toString() +":" + two + "," + s3.toString() + ":" + three;
                                JSONObject data1 = getDataForSpec(multiUnitPriceMap,dataMap,explainMap,s1.toString(),one,s2.toString(),two,s3.toString(),three);
                                specDetails.add(data1);
                                specKeyList.add(specKey);
                            }
                        } else {
                            JSONObject data2 = getDataForSpec(multiUnitPriceMap,dataMap,explainMap,s1.toString(),one,s2.toString(),two);
                            specDetails.add(data2);
                            String specKey = s1.toString() + ":" + one + "," + s2.toString() +":" + two;
                            specKeyList.add(specKey);
                        }
                    }
                } else {
                    JSONObject data3 =getDataForSpec(multiUnitPriceMap,dataMap,explainMap,s1.toString(),one);
                    specDetails.add(data3);
                    String specKey = s1.toString() + ":" + one;
                    specKeyList.add(specKey);
                }
            }
            boolean isNew = Objects.equals(specKeyList.size(),originProductList.size());
            for (int i = 0 ; i < originProductList.size();i++) {
                PaasFormDataEntityExt entity = originProductList.get(i);
                JSONObject dataList = entity.getData();
                JSONObject childProductObj = new JSONObject();
                JSONObject specObj = JSONObject.parseObject(dataList.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()), JSONObject.class, Feature.OrderedField);
                Double cost = dataList.getDouble(ProductEnum.COST.getAttr());
                Double stock = dataList.getDouble(ProductEnum.STOCK.getAttr());
                Double price = dataList.getDouble(ProductEnum.PRICE.getAttr());
                String barcode = dataList.getString(ProductEnum.BARCODE.getAttr());
                Integer enable = dataList.getInteger(ProductEnum.ENABLE_SKU.getAttr());

                stock = attrDecimalPrecisionHelper.setPrecision(stock, explainMap, ProductEnum.STOCK.getAttr());

                totalStock += stock;
                childProductObj.put("childProductId", entity.getDataId());
                childProductObj.put("specType", specObj);
                childProductObj.put("specCode", dataList.getString(ProductEnum.PRODUCT_NO.getAttr()));
                childProductObj.put(ProductEnum.COST.getAttr(), cost);
                childProductObj.put(ProductEnum.PRICE.getAttr(), price);
                childProductObj.put("productCode", barcode == null ? "" : barcode);
                childProductObj.put("enable",enable);
                childProductObj.put("specKey",isNew ? specKeyList.get(i) : "");
                childProductObj.put("stock",stock);
                //specDetails.add(childProductObj);
            }
            if (Objects.equals(saasAnalysisDataDTO.getFromOuterLink(), BasicConstant.ONE) || Objects.equals(saasAnalysisDataDTO.getPlatform(),StringConstant.PLATFORM_DINGTALK)){
                Integer costAccuracy = explainMap.get(ProductEnum.COST.getAttr()).getAccuracy();
                String costStr = productModel.getPriceOrCostRegion(originProductList,ProductEnum.COST.getAttr(),costAccuracy);
                data.put(ProductEnum.COST.getAttr(),costStr);
                //多单位产品都需要做价格排序
                String priceStr;
                if (enableMultiUnit) {
                    priceStr = productModel.getPriceOrCostRegion(multiProductList, ProductEnum.PRICE.getAttr(), priceAccuracy);
                }else {
                    priceStr = productModel.getPriceOrCostRegion(originProductList,ProductEnum.PRICE.getAttr(),priceAccuracy);
                }
                data.put(ProductEnum.PRICE.getAttr(),priceStr);
                data.put(ProductEnum.STOCK.getAttr(),totalStock);
            }
            //高级规格模式时会有一个子产品列表，如果开启了进销存每个子产品都会有自己关联的分仓库存
            specificationObj.put("specDetails", specDetails);
        }
        data.put(ProductEnum.SPECIFICATION.getAttr(), specificationObj);
        if (Objects.equals(saasAnalysisDataDTO.getFromOuterLink(), BasicConstant.ONE)) {
            // 外链不需要后面的处理
            return;
        }
        // --------------------------供应商----------------------------------------
        List<SupplierProductEntity> supplierProductList = supplierProductModel.getSupplierProductByParentId(corpid, saasAnalysisDataDTO.getDataId());
        JSONArray supplierArr = new JSONArray();
        Map<Long, String> supplierNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (SupplierProductEntity supplierProductEntity : supplierProductList) {
            supplierNameMap.put(supplierProductEntity.getSupplierId(), supplierProductEntity.getSupplierName());
        }
        for (Map.Entry<Long, String> entry : supplierNameMap.entrySet()) {
            JSONObject supplierObj = new JSONObject();
            supplierObj.put(StringConstant.SAAS_LINK_BUSINESS_ID, entry.getKey());
            supplierObj.put(StringConstant.SAAS_LINK_BUSINESS_NAME, entry.getValue());
            supplierArr.add(supplierObj);
        }
        data.put(ProductEnum.SUPPLIER.getAttr(), supplierArr);
        List<Long> warehouseIdList = warehouseModel.getWarehouseIdsByPermission(saasAnalysisDataDTO.getLoginUser(),saasAnalysisDataDTO.getLoginUser().getDepSet());
        warehouseIdList.add(ProductConstant.ALL_WAREHOUSE_ID);
        List<String> fieldList = Arrays.asList(ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr("warehouseId"), ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr("warehouseName"), "id", ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr("stockUpperLimit"), ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr("stockLowerLimit"), ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr("isNotify"), ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr("productId"),ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.WAREHOUSE_CHECKED));
        List<ProductWarehouseEntity> warehouseRelationList = productWarehouseModel.getProductWareHouseByParentIdAndWarehouseIdIn(corpid, saasAnalysisDataDTO.getDataId(), warehouseIdList, fieldList, null);
        JSONArray notifySubFormArr = new JSONArray();
        Map<Long, String> warehouseNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (ProductWarehouseEntity productWarehouseEntity : warehouseRelationList) {
            warehouseNameMap.put(productWarehouseEntity.getWarehouseId(), productWarehouseEntity.getWarehouseName());
            if (Objects.equals(productWarehouseEntity.getIsNotify(), 1)) {
                JSONObject notifySubFormObj = new JSONObject();
                PaasFormDataEntityExt paasFormDataEntityExt = childMap.getOrDefault(productWarehouseEntity.getProductId(), new PaasFormDataEntityExt());
                JSONArray specArr = new JSONArray();
                if (Objects.equals(advancedMode, 0)) {
                    String spec = getStringOrDefaultFromFormData(paasFormDataEntityExt.getData(), ProductEnum.SPECIFICATION_LINK_TEXT.getAttr(), "");
                    JSONObject obj = new JSONObject();
                    obj.put(spec, spec);
                    specArr.add(obj);
                } else {
                    List<SpecificationEntity> specificationList = specificationModel.getSpecificationList(corpid, saasAnalysisDataDTO.getDataId());
                    JSONObject specObj = FastJsonHelper.getJsonObjectOrDefaultFromFormData(paasFormDataEntityExt.getData(), ProductEnum.SPECIFICATION_LINK_TEXT.getAttr(), new JSONObject());
                    Map<String, String> specMap = JSONObject.parseObject(specObj.toJSONString(), new TypeReference<Map<String, String>>(){});
                    for (SpecificationEntity specificationEntity : specificationList) {
                        if (specMap.containsKey(specificationEntity.getName())) {
                            JSONObject spec = new JSONObject();
                            spec.put(specificationEntity.getName(), specMap.get(specificationEntity.getName()));
                            specArr.add(spec);
                        }
                    }
                }
                JSONArray warehouseArr = new JSONArray();
                JSONObject warehouseObj = new JSONObject();
                warehouseObj.put(StringConstant.SAAS_LINK_BUSINESS_ID, productWarehouseEntity.getWarehouseId());
                warehouseObj.put(StringConstant.SAAS_LINK_BUSINESS_NAME, productWarehouseEntity.getWarehouseName());
                warehouseArr.add(warehouseObj);
                notifySubFormObj.put(ProductNotifyEnum.WAREHOUSE_NAME.getAttr(), warehouseArr);
                notifySubFormObj.put(ProductNotifyEnum.SPECIFICATION.getAttr(), specArr);
                notifySubFormObj.put(ProductNotifyEnum.STOCK_LOWER_LIMIT.getAttr(), productWarehouseEntity.getStockLowerLimit());
                notifySubFormObj.put(ProductNotifyEnum.STOCK_UPPER_LIMIT.getAttr(), productWarehouseEntity.getStockUpperLimit());
                notifySubFormArr.add(notifySubFormObj);
            }
        }
        JSONArray warehouseArr = new JSONArray();
        warehouseNameMap.remove(ProductConstant.ALL_WAREHOUSE_ID);
        for (Map.Entry<Long, String> entry : warehouseNameMap.entrySet()) {
            JSONObject warehouseObj = new JSONObject();
            warehouseObj.put(StringConstant.SAAS_LINK_BUSINESS_ID, entry.getKey());
            warehouseObj.put(StringConstant.SAAS_LINK_BUSINESS_NAME, entry.getValue());
            warehouseArr.add(warehouseObj);
        }
        data.put(ProductEnum.WAREHOUSE.getAttr(), warehouseArr);
        data.put(ProductEnum.STOCK_NOTIFY.getAttr(), notifySubFormArr);
        // 兼容线上全仓预警和现在的开启预警
        if (!notifySubFormArr.isEmpty()) {
            data.put(ProductEnum.IS_NOTIFY.getAttr(), 1);
        }
    }



    private Map<String , PaasFormDataEntityExt> makeDataMap(List<PaasFormDataEntityExt> originProductList,StringBuilder s1,List<String> c1,StringBuilder s2,List<String> c2,StringBuilder s3,List<String> c3){
        Map<String , PaasFormDataEntityExt> dataMap = new HashMap<>();
        for (int i =0;i<originProductList.size();i++){
            PaasFormDataEntityExt entityExt = originProductList.get(i);
            JSONObject dataList = entityExt.getData();
            JSONObject specObj = dataList.getJSONObject(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr());
            String sv1 = specObj.getString(s1.toString());
            if (Objects.equals(s2.toString().length(),0)){
                String specKey = s1.toString() + ":" + sv1;
                dataMap.put(specKey,entityExt);
                continue;
            }
            String sv2 =  specObj.getString(s2.toString());
            if (Objects.equals(s3.toString().length(),0)){
                String specKey = s1.toString() + ":" + sv1 + "," + s2.toString() + ":" + sv2;
                dataMap.put(specKey,entityExt);
                continue;
            }
            String sv3 =  specObj.getString(s3.toString());
            String specKey = s1.toString() + ":" + sv1 + "," + s2.toString() + ":" + sv2 + "," + s3.toString() + ":" + sv3;
            dataMap.put(specKey,entityExt);
        }
        return dataMap;
    }

    private JSONObject getDataForSpec(Map<Long, Object> multiUnitPriceMap,Map dataMap,Map<String, FieldAttrEntity> explainMap,String ... spec){
        int count = spec.length;
        StringBuilder sb = new StringBuilder();
        JSONObject specOb = new JSONObject();
        switch (count){
            case 2:
                sb.append(spec[0] + ":" + spec[1]);
                specOb.put(spec[0],spec[1]);
                break;
            case 4:
                sb.append(spec[0] + ":" + spec[1] + "," + spec[2] + ":" + spec[3]);
                specOb.put(spec[0],spec[1]);
                specOb.put(spec[2],spec[3]);
                break;
            case 6:
                sb.append(spec[0] + ":" + spec[1] + "," + spec[2] + ":" + spec[3] + "," + spec[4] + ":" + spec[5]);
                specOb.put(spec[0],spec[1]);
                specOb.put(spec[2],spec[3]);
                specOb.put(spec[4],spec[5]);
                break;
        }
        JSONObject childProductObj = new JSONObject();

        childProductObj.put("childProductId", null);
        childProductObj.put("specType", specOb);
        childProductObj.put("specCode", "");
        childProductObj.put(ProductEnum.COST.getAttr(), 0);
        childProductObj.put(ProductEnum.PRICE.getAttr(), 0);
        childProductObj.put("productCode", "");
        childProductObj.put("productImage", "");
        childProductObj.put("enable",0);
        childProductObj.put("specKey",sb.toString());
        childProductObj.put("stock",0);

        JSONObject childProductOb = null;
        if (Objects.nonNull(dataMap.get(sb.toString()))){
            childProductOb = new JSONObject();
            PaasFormDataEntityExt entityExt = (PaasFormDataEntityExt)dataMap.get(sb.toString());
            double totalStock = 0.0D;
            JSONObject dataList = entityExt.getData();
            JSONObject specObj = JSONObject.parseObject(dataList.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()), JSONObject.class, Feature.OrderedField);
            //新增权限校验
            Double cost = dataList.getDouble(ProductEnum.COST.getAttr());
            Double stock = dataList.getDouble(ProductEnum.STOCK.getAttr());
            Double price = dataList.getDouble(ProductEnum.PRICE.getAttr());
            String barcode = dataList.getString(ProductEnum.BARCODE.getAttr());
            Integer enable = dataList.getInteger(ProductEnum.ENABLE_SKU.getAttr());

            stock = attrDecimalPrecisionHelper.setPrecision(stock, explainMap, ProductEnum.STOCK.getAttr());

            totalStock += stock;
            childProductOb.put("childProductId", entityExt.getDataId());
            childProductOb.put("specType", specObj);
            childProductOb.put("specCode", dataList.getString(ProductEnum.PRODUCT_NO.getAttr()));
            childProductOb.put(ProductEnum.COST.getAttr(), cost);
            if (multiUnitPriceMap.containsKey(entityExt.getDataId())) {
                childProductOb.put(ProductEnum.PRICE.getAttr(), multiUnitPriceMap.get(entityExt.getDataId()));
            }else {
                childProductOb.put(ProductEnum.PRICE.getAttr(), price);
            }
            JSONArray jsonArray = JSON.parseArray(dataList.getString(ProductEnum.PRODUCT_IMGS.getAttr()));
            childProductOb.put("productImage", jsonArray);
            childProductOb.put("productCode", barcode == null ? "" : barcode);
            childProductOb.put("enable",enable);
            childProductOb.put("specKey",sb.toString());
            childProductOb.put("stock",stock);
        }
        return childProductOb == null ? childProductObj : childProductOb;
    }


    public Double approvalSetBusinessUnit(JSONObject jsonObject, BusinessUnitProductEntity businessUnitProductEntity) {
        if (Objects.nonNull(jsonObject) && Objects.nonNull(jsonObject.get(SelectProductEnum.BUSINESS_UNIT.getAttr()))) {
            businessUnitProductEntity.setBusinessUnit(jsonObject.getLong(SelectProductEnum.BUSINESS_UNIT.getAttr()));
            businessUnitProductEntity.setRate(jsonObject.getDouble(SelectProductEnum.RATE.getAttr()));
            businessUnitProductEntity.setGroupId(jsonObject.getLong(SelectProductEnum.UNIT_GROUP.getAttr()));
            businessUnitProductEntity.setBusinessNum(jsonObject.getDouble(SelectProductEnum.BUSINESS_NUM.getAttr()));
            businessUnitProductEntity.setProductNum(jsonObject.getDouble(SelectProductEnum.NUM.getAttr()));
            JSONObject priceData = new JSONObject();
            priceData.put(SelectProductEnum.PRICE.getAttr(), jsonObject.get(SelectProductEnum.BUSINESS_PRICE.getAttr()));
            priceData.put(SelectProductEnum.COST.getAttr(), jsonObject.get(SelectProductEnum.BUSINESS_COST.getAttr()));
            priceData.put(SelectProductEnum.SELLING_PRICE.getAttr(), jsonObject.get(SelectProductEnum.BUSINESS_SELLING_PRICE.getAttr()));
            businessUnitProductEntity.setPriceData(priceData);
        }
        if (Objects.nonNull(jsonObject) && Objects.nonNull(businessUnitProductEntity.getBusinessUnit())) {
            jsonObject.put(SelectProductEnum.NUM.getAttr(), Arith.div(Math.abs(businessUnitProductEntity.getProductNum()), businessUnitProductEntity.getRate()));
            jsonObject.put(SelectProductEnum.UNIT.getAttr(), businessUnitProductEntity.getBusinessUnit());
            jsonObject.put(SelectProductEnum.BUSINESS_NUM.getAttr(), businessUnitProductEntity.getProductNum());
            JSONObject priceData = businessUnitProductEntity.getPriceData();
            if (Objects.nonNull(priceData) && !priceData.isEmpty()) {
                if (Objects.nonNull(priceData.get(SelectProductEnum.PRICE.getAttr()))){
                    jsonObject.put(SelectProductEnum.PRICE.getAttr(),priceData.get(SelectProductEnum.PRICE.getAttr()));
                }
                if (Objects.nonNull(priceData.get(SelectProductEnum.COST.getAttr()))){
                    jsonObject.put(SelectProductEnum.COST.getAttr(),priceData.get(SelectProductEnum.COST.getAttr()));
                }
                if (Objects.nonNull(priceData.get(SelectProductEnum.SELLING_PRICE.getAttr()))){
                    jsonObject.put(SelectProductEnum.SELLING_PRICE.getAttr(),priceData.get(SelectProductEnum.SELLING_PRICE.getAttr()));
                }
            }
            businessUnitProductEntity.setProductUnit(businessUnitProductEntity.getBusinessUnit().toString());
        }
        return businessUnitProductEntity.getRate() == null ? 1D : businessUnitProductEntity.getRate();
    }
}
